
//
// 120714 - AH - (Kryddar) Created.
// 120721 - AH - (Midtun) getSocratons().
// 120811 - AH - (Midtun *) Now holds BisonSource objects not Bison objects.
// 121021 - AH - (Midtun) Now throw exception if Socratons not found on Orb,
//               used to create.
// 121125 - AH - (Midtun *) Removed references to the Orb and getOrb() method:
//               ConversationEvent now has it.
//

package org.soekrat.engine.captor.event;

import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.japril.jutil.logging.Log;
import org.soekrat.conversationevent.ConversationEvent;
import org.soekrat.engine.captor.Captor;
import org.soekrat.engine.socraton.Bison;
import org.soekrat.engine.socraton.BisonSource;
import org.soekrat.environment.Orb;

/**
 * <p>
 *   Event
 *   {@link Captor} publishes to 
 *   {@link CaptorListener}. 
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC)
 */
public final class CaptorEvent extends ConversationEvent 
{
  private final String m_oname;
  
  private Object m_captured;
  
  private final List<BisonSource> m_bisons=new ArrayList<BisonSource>();
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param source   {@link #getSource()}. 
   * @param oname    {@link #getOntologyName()}, {@code null} if does not apply.
   * @param captured {@link #getCaptured()}.
   * @param orb      {@link #getOrb()}.
   */
  public CaptorEvent(Captor source, String oname, Object captured, Orb orb)
  { 
    super(source, orb);
    
    Log.log(c_log, this, "CaptorEvent", "ontology-name: "+oname);
    Log.log(c_log, this, "CaptorEvent", "captured: "+captured);
    
    m_oname=oname;
    m_captured=captured;
    
    initialized(source, captured, orb, null);
  }
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param source   {@link #getSource()}. 
   * @param oname    {@link #getOntologyName()}, {@code null} if does not apply.
   * @param captured {@link #getCaptured()}.
   * @param orb      {@link #getOrb()}.
   * @param bisons   {@link Bison}s captured.
   */
  public CaptorEvent(Captor source, String oname, Object captured, Orb orb, 
    Bison... bisons)
  { 
    super(source, orb);
    
    m_oname=oname;
    
    if (bisons==null)
    {
      throw new NullPointerException("bisons");
    }
    
    Log.log(c_log, this, "CaptorEvent", "ontology-name: "+oname);
    Log.log(c_log, this, "CaptorEvent", "captured: "+captured);
    if (bisons!=null) 
      Log.log(c_log, this, "CaptorEvent", "bisons: "+Arrays.toString(bisons));
    
    initialized(source, captured, orb, bisons);
  }
  
  /**
   * <p>
   *   Gets qualified class name on ontology {@code this} is for.
   * </p>
   * @return Name or {@code null} if does not apply.
   */
  public String getOntologyName(){ return m_oname; }
  
  private void initialized(Captor source, Object captured, Orb orb, 
    Bison[] bisons)
  {
    m_captured=captured;
    
    int n=(bisons==null) ? 0 : bisons.length;
    for (int i=0; i<n; i++)
    {
      Bison bison=bisons[i];
      if (bison==null)
      {
        throw new NullPointerException("bison["+i+"]");
      }
      
      m_bisons.add(bison);
    }
  }
  
  /**
   * <p>
   *   Gets number of
   *   {@link BisonSource}s {@code this} has.
   * </p>
   * @return Count.
   */
  public int getBisonSourceCount(){ return m_bisons.size(); }
  
  /**
   * <p>
   *   Gets
   *   {@link BisonSource}.
   * </p>
   * @param idx Index of source to get.
   * @return {@code BisonSource}.
   * @throws IndexOutOfBoundsException If 
   *         {@code idx<0 || idx>=getBisonSourceCount()}.
   */
  public BisonSource getBisonSource(int idx){ return m_bisons.get(idx); }
  
  /**
   * <p>
   *   Gets captured
   *   {@link Bison}s.
   * </p>
   * @return {@code Bison}s.
   */
  public List<Bison> getBisons()
  {
    List<Bison> bisons=new ArrayList<Bison>();
    for (BisonSource bs : m_bisons) bs.getBisons(bisons);
    return bisons;
  }
 
  /**
   * <p>
   *   Gets type of data captured.
   * </p>
   * @return {@link Class} of captured data.
   */
  public Class<?> getCapturedType(){ return m_captured.getClass(); }
  
  /**
   * <p>
   *   Gets captured data.
   * </p>
   * @return Captured.
   */
  public Object getCaptured(){ return m_captured; }
  
  @Override
  public String toString()
  {
    CharArrayWriter caw=new CharArrayWriter();
    PrintWriter pw=new PrintWriter(caw);
    
    StringBuilder sb=new StringBuilder();
    sb.append("capturd: ").append(m_captured);
    pw.println(sb.toString());
    
    pw.println("bisons:");
    
    for (BisonSource bison : m_bisons)
    {
      sb.setLength(0);
      sb.append("  ").append(bison);
      pw.println(sb.toString());  
    }
    
    pw.flush();
    return caw.toString();
  }
  
  private static final boolean c_log=true;
  
}
